package com.mytime;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import com.mytime.entity.Event;
import com.mytime.util.DataInput;
import com.mytime.util.Time;

public class ScheduleOrganizer {

	private static JSONObject dayEvents = new JSONObject();
	
	/**
	 * Get Events from server and sort this events by time.
	 * This method connects to the server and gets all active events.
	 * @throws JSONException 
	 * **/
	public static void getData() throws JSONException {
		JSONArray events = new JSONArray();
		JSONObject data = new JSONObject();

		//Change lines below
		data = DataInput.getEvents();
		if (!data.has("events"))
			return;
		
		events = data.getJSONArray("events");
		
		//CHANGE HERE!!!!!!!!!!
		//Connects to the Webservice.		
		//Retrieve JSONObject containing all events.		
		//Iterate over JSONObject to add Events to the list.
		
		//Returns the list.
		sortEvents(events);
	}
		
	/**
	 * Organizes a schedule to the user.
	 * **/
	public static List<Event> organizeSchedule(Time startTime) throws JSONException {
		ArrayList<Event> schedule = new ArrayList<Event>();
		
		//Gets data from webservice and sorts it by starting time.
		ScheduleOrganizer.getData();
		
		if (dayEvents.length() == 0)
			return schedule;
	
		//Generate schedule
		Time nextAvailableTime = startTime;
		Time displacementTime = new Time(); 
		//Event lastEventAdded = null;
		
		//Chooses the events
		for (int i = startTime.getHour(); i < 25; i++) {
			String key = String.valueOf(i);	
			
			if (!dayEvents.has(key) || i < nextAvailableTime.getHour())
				continue;
			System.out.println(key);
			JSONArray events = dayEvents.getJSONArray(key);
			for (int j = 0; j < events.length(); j++) {
				JSONObject eventObj = events.getJSONObject(j);
				Event event =  new Event(eventObj);

				//Gets event start time
				Time eventStartTime = new Time(eventObj.getString("startTime"));

				//Calculate displacement time
				//displacementTime = calculateDisplacementeTime(lastEvendAdded.getLocal(), event.getLocal());
				displacementTime = calculateDisplacementeTime();
				
				//Event can only be added if it starts after timeForEvent  
				Time timeForEvent = nextAvailableTime.addTo(displacementTime);
				System.out.println("next: " + nextAvailableTime.getTime());
				System.out.println("event start: " + eventStartTime.getTime());
				
				int comparator = timeForEvent.compareTo(eventStartTime);
				System.out.println("comp: " + comparator);
				//nextAvailableTime + displacementTime < eventStartTime 
				if (comparator < 0) {
					schedule.add(event);
					//lastEventAdded = event;
					
					//Updates next available time
					nextAvailableTime.changeTime(eventObj.getString("endTime"));
				
				//nextAvailableTime + displacementTime = eventStartTime
				} else if (comparator == 0) {					
					schedule.add(event);
					//lastEventAdded = event;
				
				//Event starts before next available time and cannot be added.
				} else {
					break;
				}
				
			}
		}
		
		for (Event e: schedule)
			System.out.println(e.toJSON());
		return schedule;
	}

	/**
	 * Groups and sorts events by their starting time.
	 * This method receives a JSONArray containing events represented by JSONObjects. Each event must have a starting time.
	 * This events will be grouped according to the time span they are in. For example, all events starting between 18:00 and 19:00
	 * will be grouped together.   
	 * @throws JSONException 
	 * **/
	@SuppressWarnings({ "unchecked", "rawtypes" })
	private static void sortEvents(JSONArray eventsFromServer) throws JSONException {		
		//No events in a day
		if (eventsFromServer.length() == 0) {
			System.out.println("No events");
			return;
		}

		//Sorting events by starting time
		for (int i = 0; i < eventsFromServer.length(); i++) {
			//Get the JSONObject that represents an event
			JSONObject event = eventsFromServer.getJSONObject(i);
			
			//Gets Event startTime
			Time startTime = new Time(event.getString("startTime")); 

			//Gets Event startHour
			int startHour = startTime.getHour();
			
			//Groups events in a JSONArray. This JSONArray is stored in eventsGrouped indexed by startHour
			JSONArray tempArray = new JSONArray();
			String key = String.valueOf(startHour);
			if (dayEvents.has(key)) {
				tempArray = dayEvents.getJSONArray(key);
			}
			tempArray.put(event);
			
			dayEvents.put(key, tempArray);
		}
		
		//Sorts events in a time span
		Iterator keysIterator = (Iterator) dayEvents.keys();
		
		while (keysIterator.hasNext()) {
			String timeKey = (String) keysIterator.next();
			JSONArray tempArray = (JSONArray) dayEvents.get(timeKey);
			
			ArrayList<Event> tempList = new ArrayList<Event>();			
			for (int i = 0; i < tempArray.length(); i++) {
				Event e = new Event((JSONObject) tempArray.get(i));
				tempList.add(e);
			}
			
			Collections.sort(tempList, new Comparator() {    
	            public int compare(Object o1, Object o2) {    
	                Event c1 = (Event) o1;    
	                Event c2 = (Event) o2;
	                
	                Time time1 = c1.getStartTime();
	                Time time2 = c2.getStartTime();
	                
	                return time1.compareTo(time2);
            	}  
			});
			
			tempArray = new JSONArray();
			for (int i = 0; i < tempList.size(); i++) {
				tempArray.put(tempList.get(i).toJSON());
			}						
			dayEvents.put(timeKey, tempArray);
		}
	}

	//private static Time calculateDisplacementeTime(Local l1, Local l2) {
	private static Time calculateDisplacementeTime() {
		return new Time();
	}
	
}
